import React from 'react';
import BaseField from '../Base/BaseField';
import BaseFormItem from '../Base/BaseFormItem';
import { DatePicker } from '../DatePicker';
import { isArray, isEmpty, isFunction, isNumber, map, omit } from 'lodash-es';
import { systemDateTimeFormat } from '../Config';
import {
    dateStr2Timestamp,
    gmt0ToCurrentTimestamp,
    curTimestampToGmt0,
    isDateIns,
    isObjectValEqual,
    newDateIns, myFormatTime,
} from 'jh-utils';
import PropTypes from 'prop-types';

import styles from './index.module.less';

const { RangePicker } = DatePicker;

/**
 *
 * @param value ①当传入 number 类型时，需要是GMT0时区的时间戳。②传入其他类型时，需要时系统时区的 Date、dayJs 实例对象
 * @return {number | Array}
 */
function dealDateValue(value) {
    let reValue = isNumber(value) && value > 9999999999 ? Math.floor(value / 1000) : value;

    if (isArray(reValue)) {
        reValue = map(reValue, (valItem) => {

            if (isDateIns(valItem)) {
                return dateStr2Timestamp(valItem);
            } else {
                return isNumber(valItem) && valItem > 9999999999 ? Math.floor(valItem / 1000) : valItem;
            }
        });

    } else if (isDateIns(reValue)) {
        reValue = dateStr2Timestamp(reValue);
    }
    return reValue;
}

function dealValOrUndefined(value) {
    let fVal;

    if (isArray(value)) {
        fVal = map(value, (val) => {
            let v = val;
            //  如果 v 是时间戳，则把 v 当成 GMT0 时区的时间戳，所以需要先将 v 转成当前用户时区的时间戳，再 newDateIns
            if (isNumber(v)) {
                v = gmt0ToCurrentTimestamp(v);
            }
            let dayIns = newDateIns(v);
            return undefined !== v && null !== v && dayIns.isValid() ? dayIns : undefined;
        });
    } else {
        let v = value;
        //  如果 v 是时间戳，则把 v 当成 GMT0 时区的时间戳，所以需要先将 v 转成当前用户时区的时间戳，再 newDateIns
        if (isNumber(v)) {
            v = gmt0ToCurrentTimestamp(v);
        }
        let dayIns = newDateIns(v);
        fVal = undefined !== v && null !== v && dayIns.isValid() ? dayIns : undefined;
    }
    return fVal;
}

class DateBase extends BaseField {

    static propTypes = {
        ...BaseField.propTypes,
        /**
         * 是否选择日期区间。默认是单日期
         */
        range: PropTypes.bool,
    };

    static getDerivedStateFromProps(nextProps, preState) {
        // 有 value，说明这是个受控组件，则以 value 为准

        if ('value' in nextProps) {
            const value = nextProps.value;

            return {
                value: dealValOrUndefined(value),
                originValue: value,
            };

        } else if (('defaultValue' in nextProps) && preState &&
            !isObjectValEqual({ defaultValue: nextProps.defaultValue }, { defaultValue: preState.defaultValue })) {
            // 如果是作为非受控组件。当 defaultValue 改变，则更新组件内的数据
            const defaultValue = nextProps.defaultValue;
            return {
                value: dealValOrUndefined(defaultValue),
                originValue: defaultValue,
                defaultValue: defaultValue,
            };
        }
        return null;
    }

    initState(props) {
        return {
            ...super.initState(props),
            value: dealValOrUndefined(props.value || props.defaultValue || null),
        };
    }

    moreCommonProps() {
        return [...super.moreCommonProps(), 'value', 'defaultValue', 'range'];
    }

    setValue(value, afterCb) {
        let val = dealDateValue(value);
        super.setValue(val, afterCb);
    }

    getValue() {
        return dealDateValue(super.getValue());
    }

    hdlValueChange(value) {
        let val = value;

        if (isArray(val)) {
            val = map(val, (valItem) => {

                if (isDateIns(valItem) && isFunction(valItem.valueOf)) {
                    return curTimestampToGmt0(valItem.valueOf());
                } else {
                    return isNumber(valItem) && valItem > 9999999999 ? Math.floor(valItem / 1000) : valItem;
                }
            });

        } else if (isDateIns(val) && isFunction(val.valueOf)) {
            // 如果 value 是 dayjs 实例，则将 value 当成是“当前时区”的 dayJs 实例，需要转成 GMT0 时区时间戳
            val = curTimestampToGmt0(val.valueOf());
        }

        console.log('DateBase valueChange:', value, val);
        super.hdlValueChange(val);
        // super.hdlValueChange(dealDateValue(value));
    }

    mainRender(context) {
        const { value } = this.state;
        const range = this.getPropsByName('range');
        const style = this.getPropsByName('style') || {};
        const format = this.getPropsByName('format') || '';
        const dropdownClassName = this.getPropsByName('dropdownClassName') || '';
        const cProps = {
            showTime: {
                defaultValue: range ?
                    [newDateIns('00:00:00', 'HH:mm:ss'), newDateIns('23:59:59', 'HH:mm:ss')] :
                    newDateIns('00:00:00', 'HH:mm:ss'),
            },
            allowClear: true,
            ...omit(this.props, this.commonProps),
            format: format || systemDateTimeFormat,
            value,
            onChange: this.hdlValueChange.bind(this),
            style: omit(style, ['height']),
            dropdownClassName: `${dropdownClassName} ${styles.dd}`,
            // dateRender: (current) => {
            // 	return (<div className="ant-picker-cell-inner"
            // 	             onClick={(e) => {
            // 		             console.log('click', current, myFormatTime(current));
            // 	             }}
            // 	             onDoubleClick={() => {
            // 		             console.log('ddClick', myFormatTime(current));
            // 		             this.hdlValueChange(current);
            // 	             }}
            // 	>
            // 		{current.date()}
            // 	</div>);
            // },
            // onOpenChange: (open) => {
            //
            // }
        };

        if (range) {
            return (
                <RangePicker {...cProps}
                             ref={(ref) => {
                                 this.nodeRef = ref;
                             }}/>
            );
        }

        return <DatePicker  {...cProps}
                            ref={(ref) => {
                                this.nodeRef = ref;
                            }}/>;
    }
}

function dealValEmpty(value) {
    let reVal = value;

    if (isArray(value)) {
        reVal = map(value, (val) => (
            (!isNumber(val) && val) ? dateStr2Timestamp(val) : val
        ));
    } else if (!isNumber(value) && value) {
        reVal = dateStr2Timestamp(value);
    }
    return reVal;
}

export default class DateComp extends BaseFormItem {

    dealValue({ value, defaultValue }) {
        let reO = {};
        reO.value = dealValEmpty(value);
        reO.defaultValue = dealValEmpty(defaultValue);
        // console.log('DateComp', reO);
        return reO;
    }

    Comp = DateBase;
}